#import "SM4Crypto.h"
#import "GMSm4Utils.h"

@implementation SM4Crypto

+ (NSDictionary *)sm4Encrypt:(NSString *)secretKey withPlainText:(NSString *)plainText {
    //获取时间戳
    NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
    long long milliseconds = (long long)(currentTime * 1000);

    NSDictionary *dic = [SM4Crypto sm4Encrypt:secretKey withPlainText:plainText withTime:milliseconds];
    return dic;
}

+ (NSDictionary *)sm4Encrypt:(NSString *)secretKey withPlainText:(NSString *)plainText withTime:(long long)milliseconds {
    NSString *originalSecretKey = [NSString stringWithString:secretKey];
    secretKey = [SM4Crypto convertStringToHexString:secretKey];
    //如果不够 32 位 补 0,超过则取前 32 位
    if (secretKey.length < 32) {
        for (int i = 0; i < 32 - secretKey.length; i++) {
            secretKey = [secretKey stringByAppendingString:@"0"];
        }
    } else if (secretKey.length > 32) {
        secretKey = [secretKey substringToIndex:32];
    }

    //ivec = 时间戳+ygj
    NSString *ivec = [NSString stringWithFormat:@"%lld%@", milliseconds, @"ygj"];

    ivec = [SM4Crypto convertStringToHexString:ivec];
    //如果不够 32 位 补 0,超过则取前 32 位
    if (ivec.length < 32) {
        for (int i = 0; i < 32 - ivec.length; i++) {
            ivec = [ivec stringByAppendingString:@"0"];
        }
    } else if (ivec.length > 32) {
        ivec = [ivec substringToIndex:32];
    }

    //CBC 加密模式
    NSString *cbcCipertext = [GMSm4Utils cbcEncryptText:plainText key:secretKey IV:ivec];
    NSData *cbcCipherData = [GMSm4Utils cbcEncryptData:[plainText dataUsingEncoding:NSUTF8StringEncoding] key:secretKey IV:ivec];

    //NSLog(@"%@", [cbcCipherData base64EncodedStringWithOptions:0]);
    //NSLog(@"%@", [[NSString alloc] initWithData:cbcCipherData encoding:NSUTF8StringEncoding]);

    NSMutableDictionary *mdic = [NSMutableDictionary dictionary];

    if (cbcCipertext) {
        mdic[@"cbcCipertext"] = cbcCipertext;
    }
    if (cbcCipherData) {
        mdic[@"cbcCipherData"] = cbcCipherData;
    }
    if (plainText) {
        mdic[@"plainText"] = plainText;
    }
    if (secretKey) {
        mdic[@"secretKey"] = secretKey;
    }
    if (originalSecretKey) {
        mdic[@"originalSecretKey"] = originalSecretKey;
    }
    if (ivec) {
        mdic[@"ivec"] = ivec;
    }
    if (@(milliseconds)) {
        mdic[@"milliseconds"] = @(milliseconds);
    }
    if ([cbcCipherData base64EncodedStringWithOptions:0]) {
        mdic[@"encodeBase64"] = [cbcCipherData base64EncodedStringWithOptions:0];
    }
    if ([[NSString alloc] initWithData:cbcCipherData encoding:NSUTF8StringEncoding]) {
        mdic[@"decodeBase64"] = [[NSString alloc] initWithData:cbcCipherData encoding:NSUTF8StringEncoding];
    }

    /**
    @{
        @"cbcCipertext" : cbcCipertext,
        @"cbcCipherData" : cbcCipherData,
        @"plainText" : plainText,
        @"secretKey" : secretKey,
        @"originalSecretKey" : originalSecretKey,
        @"ivec" : ivec,
        @"milliseconds" : @(milliseconds),
        @"encodeBase64" : [cbcCipherData base64EncodedStringWithOptions:0]
    };
     */

    return mdic;
}

+ (NSDictionary *)sm4Decrypt:(NSString *)secretKey withPlainText:(NSString *)plainText {
    //获取时间戳
    NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
    long long milliseconds = (long long)(currentTime * 1000);

    NSDictionary *dic = [SM4Crypto sm4Decrypt:secretKey withPlainText:plainText withTime:milliseconds];
    return dic;
}

+ (NSDictionary *)sm4Decrypt:(NSString *)secretKey withPlainText:(NSString *)plainText withTime:(long long)milliseconds {
    NSString *originalSecretKey = [NSString stringWithString:secretKey];
    secretKey = [SM4Crypto convertStringToHexString:secretKey];
    //如果不够 32 位 补 0,超过则取前 32 位
    if (secretKey.length < 32) {
        for (int i = 0; i < 32 - secretKey.length; i++) {
            secretKey = [secretKey stringByAppendingString:@"0"];
        }
    } else if (secretKey.length > 32) {
        secretKey = [secretKey substringToIndex:32];
    }

    //ivec = 时间戳+ygj
    NSString *ivec = [NSString stringWithFormat:@"%.0f%@", milliseconds, @"ygj"];

    ivec = [SM4Crypto convertStringToHexString:ivec];
    //如果不够 32 位 补 0,超过则取前 32 位
    if (ivec.length < 32) {
        for (int i = 0; i < 32 - ivec.length; i++) {
            ivec = [ivec stringByAppendingString:@"0"];
        }
    } else if (ivec.length > 32) {
        ivec = [ivec substringToIndex:32];
    }

    //CBC 解密模式
    NSString *cbcPlaintext = [GMSm4Utils cbcDecryptText:plainText key:secretKey IV:ivec];
    NSData *cbcDecryptData = [GMSm4Utils cbcDecryptData:[plainText dataUsingEncoding:NSUTF8StringEncoding] key:secretKey IV:ivec];

    NSMutableDictionary *mdic = [NSMutableDictionary dictionary];

    if (cbcPlaintext) {
        mdic[@"cbcPlaintext"] = cbcPlaintext;
    }
    if (cbcDecryptData) {
        mdic[@"cbcDecryptData"] = cbcDecryptData;
    }
    if (plainText) {
        mdic[@"plainText"] = plainText;
    }
    if (secretKey) {
        mdic[@"secretKey"] = secretKey;
    }
    if (originalSecretKey) {
        mdic[@"originalSecretKey"] = originalSecretKey;
    }
    if (ivec) {
        mdic[@"ivec"] = ivec;
    }
    if (@(milliseconds)) {
        mdic[@"milliseconds"] = @(milliseconds);
    }
    if ([cbcDecryptData base64EncodedStringWithOptions:0]) {
        mdic[@"encodeBase64"] = [cbcDecryptData base64EncodedStringWithOptions:0];
    }
    if ([[NSString alloc] initWithData:cbcDecryptData encoding:NSUTF8StringEncoding]) {
        mdic[@"decodeBase64"] = [[NSString alloc] initWithData:cbcDecryptData encoding:NSUTF8StringEncoding];
    }

    /**
    return @{
        @"cbcPlaintext" : cbcPlaintext,
        @"cbcDecryptData" : cbcDecryptData,
        @"plainText" : plainText,
        @"secretKey" : secretKey,
        @"originalSecretKey" : originalSecretKey,
        @"ivec" : ivec,
        @"milliseconds" : @(milliseconds),
        @"encodeBase64" : [cbcDecryptData base64EncodedStringWithOptions:0],
        @"decodeBase64" : [[NSString alloc] initWithData:cbcDecryptData encoding:NSUTF8StringEncoding]
    };
     */

    return mdic;
}

+ (NSString *)convertStringToHexString:(NSString *)string {
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableString *hexString = [NSMutableString stringWithCapacity:data.length * 2];

    const unsigned char *bytes = data.bytes;
    for (NSInteger i = 0; i < data.length; i++) {
        [hexString appendFormat:@"%02x", bytes[i]];
    }

    return [hexString copy];
}

+ (NSString *)encodeBase64:(NSString *)input {
    if (!input) {
        return nil;
    }

    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
    return [data base64EncodedStringWithOptions:0];
}

+ (NSString *)decodeBase64:(NSString *)input {
    if (!input) {
        return nil;
    }

    NSData *data = [[NSData alloc] initWithBase64EncodedString:input options:0];
    if (!data) {
        return nil;
    }

    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

@end
